﻿using SerialPortHelperLib;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using XModem.library;

namespace BinAnalysisHelp
{
    public class BinXModem
    {
        private SerialPortHelper serialPort1;
        private SerialPortHelper serialPort2;
        //爆序号
        private int PackageTemp = 0;
        //判断是c 还是nak
        private int useCRC = -1;
        //盘是1kxmodem 还是xmodem
        private bool useBlock1K;
        //用来存储接收到的文件
        private List<List<byte>> receiveList;
        //是否结束当前发送
        private bool isSend = true;
        //是否开启打印
        private bool isPrintShow = false;
        private bool isFinish = false;
        public   string SavePath;



        /// <summary>
        /// 定义委托
        /// </summary>
        /// <param name="arrDataReceived">接收到的数据帧</param>
        public delegate void DelegateSerialPortDataReceivedProcessEvent(object sender, byte[] arrDataReceived);

        /// <summary>
        /// 定义事件
        /// </summary>
        public event DelegateSerialPortDataReceivedProcessEvent EventSerialPortDataReceivedProcess;
        /// <summary>
        /// 定义委托
        /// </summary>
        /// <param name="numError">错误代号</param>
        /// <param name="strError">错误信息</param>
        public delegate void DelegateSerialPortErrorEvent(object sender, enumSerialError enumError, string strError);

        /// <summary>
        /// 定义事件
        /// </summary>
        public event DelegateSerialPortErrorEvent EventSerialPortError;

        List<XmodemRequest> rxtemplists = new List<XmodemRequest>();
        public void InitializeSerialPort()
        {
            serialPort1 = new SerialPortHelper();
            //发送使用的串口通讯
            serialPort1.BindSerialPortDataReceivedProcessEvent(new SerialPortHelper.DelegateSerialPortDataReceivedProcessEvent(SerialPortDataReceivedProcess1));
            serialPort1.BindSerialPortErrorEvent(new SerialPortHelper.DelegateSerialPortErrorEvent(SerialPortErrorProcess));
            serialPort1.SerialReceviedTimeInterval = 10; //接收数据时间
            serialPort1.SerialReceviedTimeInterval = 1;  //发送数据时间
                                                         //serialPort1.SPort.WriteTimeout = 3000;
                                                         //serialPort1.SPort.ReadTimeout = 3000;
            serialPort2 = new SerialPortHelper();
            //接收使用的串口通讯
            serialPort2.BindSerialPortDataReceivedProcessEvent(new SerialPortHelper.DelegateSerialPortDataReceivedProcessEvent(SerialPortDataReceivedProcess2));
            serialPort2.BindSerialPortErrorEvent(new SerialPortHelper.DelegateSerialPortErrorEvent(SerialPortErrorProcess));
            serialPort2.SerialReceviedTimeInterval = 1; //接收数据时间
            serialPort2.SerialReceviedTimeInterval = 1;  //发送数据时间
                                                         //serialPort2.SPort.WriteTimeout = 3000;
                                                         //serialPort2.SPort.ReadTimeout = 3000;

        }
       
        /// <summary>
        /// 导出
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="arrDataReceived"></param>
        private void SerialPortDataReceivedProcess2(object sender, byte[] arrDataReceived)
        {
            if (null != EventSerialPortDataReceivedProcess)
            {
                EventSerialPortDataReceivedProcess(sender, arrDataReceived);
            }

                //try
                //{
                //    if (arrDataReceived.Length != (useBlock1K ? 1028 : 132))
                //    {
                //        if (arrDataReceived.First() == 04)//表示结束接收
                //        {
                //            serialPort2.Write(new byte[] { 0x06, 0x06, 0x06, 0x06 }); //告诉终端结束这次发送
                //            Thread.Sleep(1000);
                //            receivePath();
                //            serialPort2.SPort.DiscardInBuffer();
                //            serialPort2.SPort.DiscardOutBuffer();
                //            //binPBC.Position = binPBC.Properties.Maximum;//设置进度条100%
                //            string msg = "导出完成！";
                //            //Fb_SendEvent(msg);
                //            serialPort2.CloseCom(out msg);
                //        //Fb_SendEvent(msg);
                //        //simpleButton4.Text = "导出";
                //        //OpenCloseFormButton(true);
                //        isFinish = true;
                //        //DevExpress.XtraEditors.XtraMessageBox.Show("导出完成，请重启设备", "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);                            
                //    }
                //        else
                //        {
                //            string msg = "->获取数据长度不够，重新获取！";
                //            //Fb_SendEvent(string.Format(msg));
                //            //simpleButton4.Text = "导出";
                //            serialPort2.CloseCom(out msg);
                //            //serialPort2.Write(new byte[] { 0x15 }); //重新NAk获取
                //        }
                //        return;
                //    }

                //    if (arrDataReceived.First() == 04)//表示结束接收
                //    {
                //        serialPort2.Write(new byte[] { 0x06, 0x06, 0x06, 0x06 }); //告诉终端结束这次发送
                //                                                                  //休眠下 导入到文件
                //        Thread.Sleep(1000);
                //        receivePath();
                //        serialPort2.SPort.DiscardInBuffer();
                //        serialPort2.SPort.DiscardOutBuffer();
                //        //binPBC.Position = binPBC.Properties.Maximum;//设置进度条100%
                //        string msg = "导出完成！";
                //        //Fb_SendEvent(msg);
                //        serialPort2.CloseCom(out msg);
                //    //Fb_SendEvent(msg);
                //    //simpleButton4.Text = "导出";
                //    //OpenCloseFormButton(true);
                //    isFinish = true;
                //    //DevExpress.XtraEditors.XtraMessageBox.Show("导出完成，请重启设备", "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                //    return;
                //    }
                //    //接收数据业务处理部分
                //    else if (arrDataReceived.First() == (useBlock1K ? 2 : 1)) //如果是1k 等于2 如果是k 就是1 处理头部分文件
                //    {
                //        List<byte> tembyte = new List<byte>();
                //        XmodemRequest xRequest = new XmodemRequest();
                //        xRequest.ControlCharacter = arrDataReceived.First();
                //        xRequest.PackageNo = arrDataReceived[1];
                //        var tempIndex = Convert.ToInt32(xRequest.PackageNo) - 1; //接收第二位
                //        xRequest.PackageInverseNo = arrDataReceived[2];

                //        byte lastCrc;
                //        //判断校验位
                //        if (useBlock1K)
                //        {
                //            xRequest.DataList = arrDataReceived.Skip(3).Take(1024).ToList();
                //            tembyte.AddRange(arrDataReceived.Skip(3).Take(1024));
                //            xRequest.CheckBit = new byte[] { arrDataReceived.Skip(1027).Take(1).First() };
                //            lastCrc = arrDataReceived.Skip(1027).Take(1).First(); //获取校验位
                //        }
                //        else
                //        {
                //            xRequest.DataList = arrDataReceived.Skip(3).Take(128).ToList();
                //            tembyte.AddRange(arrDataReceived.Skip(3).Take(128));
                //            xRequest.CheckBit = new byte[] { arrDataReceived.Skip(131).Take(1).First() };
                //            lastCrc = arrDataReceived.Skip(131).Take(1).First(); //获取校验位
                //        }
                //        if (lastCrc != BitConverter.GetBytes(XModem.library.Port.GetCkSum(tembyte.ToArray()))[0]) //判断校验位是否正确
                //        {
                //            //Fb_SendEvent(string.Format("校验位不正确重新发送NAK"));
                //            serialPort2.Write(new byte[] { 0x15 }); //重新NAk获取

                //        }
                //        else
                //        {
                //            serialPort2.Write(new byte[] { 0x06 }); //获取下一个
                //            //if (tempIndex != tempReceived)
                //            //{
                //            //    tempSize++;
                //            //    binPBC.Position += 1;
                //            //}

                //            //xRequest.No = tempSize;
                //            //Fb_SendEvent(string.Format("->导出数据{0}包", tempSize));

                //            //templists.Add(tembyte.ToList()); //用来查看包
                //            rxtemplists.Add(xRequest);
                //            //tempReceived = tempIndex;
                //        }

                //    }
                //    else if (arrDataReceived.First() == 24)
                //    {
                //        //simpleButton4.Text = "导出";
                //        string msg = "连接超时！";
                //        //Fb_SendEvent(msg);
                //        serialPort2.CloseCom(out msg);
                //        //Fb_SendEvent(msg);
                //        //OpenCloseFormButton(true);
                //    }
                //    else
                //    {
                //        serialPort2.Write(new byte[] { 0x15 }); //重新NAk获取
                //    }

                //    if (!isSend)
                //    {
                //        //Thread.Sleep(1000);
                //        //binPBC.Position = binPBC.Properties.Maximum;//设置进度条100%
                //        //simpleButton4.Text = "导出";
                //        serialPort2.Write(new byte[] { 0x18 }); //告诉终端结束这次发送
                //        Thread.Sleep(50);
                //        serialPort2.Write(new byte[] { 0x18 }); //告诉终端结束这次发送
                //        Thread.Sleep(50);
                //        serialPort2.Write(new byte[] { 0x18 }); //告诉终端结束这次发送
                //        Thread.Sleep(50);
                //        serialPort2.Write(new byte[] { 0x18 }); //告诉终端结束这次发送
                //        Thread.Sleep(50);
                //        string msg = "取消命令已发送！";
                //        //Fb_SendEvent(msg);
                //        serialPort2.CloseCom(out msg);
                //        //Fb_SendEvent(msg);
                //    }
                //}
                //catch (Exception ex)
                //{
                //    //simpleButton4.Text = "导出";
                //    serialPort2.DiscardInBuffer();
                //    string msg = "导出错误信息:";
                //    //Fb_SendEvent(msg);
                //    serialPort2.CloseCom(out msg);
                //    //OpenCloseFormButton(true);
                //    //Fb_SendEvent(string.Format("导出错误信息：{0}", ex.Message.ToString()));
                //}


           
        }

        public class ListByteComparer : IEqualityComparer<XmodemRequest>
        {
            public bool Equals(XmodemRequest x, XmodemRequest y)
            {
                return x.No == y.No;
            }

            public int GetHashCode(XmodemRequest obj)
            {
                return obj.ToString().GetHashCode();
            }
        }
        /// <summary>
        /// 导出路径
        /// </summary>
        /// <param name="path"></param>
        private void receivePath()
        {
            //保存数据到路劲下
            //去除重复数据据
            rxtemplists = rxtemplists.Distinct(new ListByteComparer()).ToList();

            using (FileStream fs = new FileStream(SavePath, FileMode.Create))
            {
                using (BinaryWriter plik = new BinaryWriter(fs))
                {
                    //if (templists.Count>= receiveTempCout)
                    //{

                    var lastrx = rxtemplists.Last();
                    if (lastrx.DataList[0] == 0x1a && lastrx.DataList[1] == 0x0 && lastrx.DataList.Last() == 0x0)
                    {
                        rxtemplists.Remove(lastrx);
                    }

                    foreach (var item in rxtemplists)
                    {

                        foreach (var temD in item.DataList)
                        {

                            plik.Write(temD);
                        }
                    }

                }
            }

        }

        private void SerialPortErrorProcess(object sender, enumSerialError enumError, string strError)
        {
            if (null != EventSerialPortError)
            {
                EventSerialPortError(sender, enumError, strError);
            }

           
        }
        /// <summary>
        /// 烧入
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="arrDataReceived"></param>
        private void SerialPortDataReceivedProcess1(object sender, byte[] arrDataReceived)
        {
            if (null !=EventSerialPortDataReceivedProcess)
            {
                EventSerialPortDataReceivedProcess(sender, arrDataReceived);
            }

            //try
            //{


            //    if (!isSend)
            //    {
            //        serialPort1.Write(new byte[] { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 });
            //        Thread.Sleep(1000); //由于在多线程中  如果需要关闭就需要添加延迟 然在关闭
            //        string msg = "烧写完成！";
            //        //Fb_SendEvent(msg);
            //        serialPort1.CloseCom(out msg);
            //        //Fb_SendEvent(msg);
            //        //binPBC.Position = binPBC.Properties.Maximum; //设置进度条100%
            //        //simpleButton3.Text = "烧写";
            //        //Fb_SendEvent("取消命令已发送！");
            //        //OpenCloseFormButton(true);
            //        serialPort1.DiscardInBuffer();
            //        isSend = true;
            //    }
            //    //Fb_SendEvent(string.Format("->接收:{1}  烧入{0}次数。。。", PackageTemp, Convert.ToString(arrDataReceived[0], 16)));
            //    //发送数据业务处理部分
            //    switch (arrDataReceived[0])
            //    {

            //        case 0x43: //表示c
            //            {
            //                useCRC = 0;

            //                if (useBlock1K)
            //                {
            //                    serialPort1.WriteByte(XmodemData.xmodem1k_C[PackageTemp].ToArray());
            //                }
            //                else
            //                {
            //                    serialPort1.WriteByte(XmodemData.xmodem_C[PackageTemp].ToArray());
            //                }
            //                //  serialPort1.DiscardInBuffer();


            //            }
            //            break;
            //        case 0x15: //表示nak
            //            {
            //                //serialPort1.WriteByte(new byte[] { 0x02 });
            //                //Fb_SendEvent("发送0x02");
            //                useCRC = 1;
            //                if (useBlock1K)
            //                {
            //                    if (PackageTemp > 0)
            //                    {
            //                        serialPort1.WriteByte(XmodemData.xmodem1k_N[PackageTemp - 1].ToArray());
            //                    }
            //                    else
            //                    {
            //                        serialPort1.WriteByte(XmodemData.xmodem1k_N[PackageTemp].ToArray());
            //                    }

            //                }
            //                else
            //                {
            //                    if (PackageTemp > 0)
            //                    {
            //                        serialPort1.WriteByte(XmodemData.xmodem_N[PackageTemp - 1].ToArray());
            //                    }
            //                    else
            //                    {
            //                        serialPort1.WriteByte(XmodemData.xmodem_N[PackageTemp].ToArray());
            //                    }

            //                }
            //                //   serialPort1.DiscardInBuffer();

            //            }
            //            break;
            //        case 0x06: //表示ack
            //            {

            //                if (useBlock1K)
            //                {
            //                    if (PackageTemp > XmodemData.xmodem1k_C.Count - 1)
            //                    {
            //                        //////发送取消命令 EOT 0x04
            //                        serialPort1.Write(new byte[] { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 });
            //                        //////这里关闭通讯 切换回以前的串口通讯
            //                        Thread.Sleep(1000); //由于在多线程中  如果需要关闭就需要添加延迟 然在关闭
            //                        string msg = "烧写完成！";
            //                        //Fb_SendEvent(msg);
            //                        serialPort1.CloseCom(out msg);
            //                        //Fb_SendEvent(msg);
            //                        //binPBC.Position = binPBC.Properties.Maximum; //设置进度条100%
            //                        //simpleButton3.Text = "烧写";
            //                        //OpenCloseFormButton(true);
            //                        isFinish = true;
            //                        serialPort1.DiscardInBuffer();
            //                        //DevExpress.XtraEditors.XtraMessageBox.Show("烧写完成", "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
            //                        ////打开串口
            //                        //if (null != OpenPortButtonClick)
            //                        //{
            //                        //    OpenPortButtonClick();
            //                        //}
            //                        return;
            //                    }
            //                }
            //                else
            //                {
            //                    if (PackageTemp > XmodemData.xmodem_C.Count - 1)
            //                    {
            //                        //////发送取消命令 EOT 0x04
            //                        serialPort1.Write(new byte[] { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 });
            //                        //////这里关闭通讯 切换回以前的串口通讯
            //                        Thread.Sleep(1000); //由于在多线程中  如果需要关闭就需要添加延迟 然在关闭
            //                        string msg = "烧写完成！";
            //                        //Fb_SendEvent(msg);
            //                        serialPort1.CloseCom(out msg);
            //                        //Fb_SendEvent(msg);
            //                        //binPBC.Position = binPBC.Properties.Maximum; //设置进度条100%
            //                        //simpleButton3.Text = "烧写";
            //                        //OpenCloseFormButton(true);
            //                        isFinish = true;
            //                        serialPort1.DiscardInBuffer();
            //                        //DevExpress.XtraEditors.XtraMessageBox.Show("烧写完成，请重启设备", "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
            //                        break;
            //                    }
            //                }


            //                if (useCRC == 0)
            //                {
            //                    if (useBlock1K)
            //                    {
            //                        serialPort1.WriteByte(XmodemData.xmodem1k_C[PackageTemp].ToArray());
            //                    }
            //                    else
            //                    {
            //                        serialPort1.WriteByte(XmodemData.xmodem_C[PackageTemp].ToArray());
            //                    }
            //                }
            //                if (useCRC == 1)
            //                {
            //                    if (useBlock1K)
            //                    {
            //                        serialPort1.WriteByte(XmodemData.xmodem1k_N[PackageTemp].ToArray());
            //                    }
            //                    else
            //                    {
            //                        serialPort1.WriteByte(XmodemData.xmodem_N[PackageTemp].ToArray());
            //                    }
            //                }
            //                //设置进度条
            //                //binPBC.Position += 1;
            //                PackageTemp++;
            //                // serialPort1.DiscardInBuffer();
            //                //Thread.Sleep(16);
            //            }
            //            break;
            //        case 0x18:
            //            {
            //                serialPort1.Write(new byte[] { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 });
            //                //simpleButton3.Text = "烧写";
            //                string msg = "烧写失败";
            //                //Fb_SendEvent(msg);
            //                serialPort1.CloseCom(out msg);
            //                //Fb_SendEvent(msg);
            //                serialPort1.DiscardInBuffer();
            //                //OpenCloseFormButton(true);
            //            }
            //            break;
            //        default:
            //            {
            //                //simpleButton3.Text = "烧写";
            //                string msg = $"接收到错误指令{arrDataReceived[0]},无法继续，烧写失败";
            //                //Fb_SendEvent(msg);
            //                serialPort1.CloseCom(out msg);
            //                //Fb_SendEvent(msg);
            //                serialPort1.DiscardInBuffer();
            //                //OpenCloseFormButton(true);
            //            }
            //            break;
            //    }

            //}
            //catch (Exception ex)
            //{
            //    //simpleButton3.Text = "烧写";
            //    string msg = "烧写失败";
            //    serialPort1.DiscardInBuffer();
            //    //Fb_SendEvent(msg);
            //    serialPort1.CloseCom(out msg);
            //    //Fb_SendEvent(string.Format("烧写错误信息：{0}", ex.Message.ToString()));
            //}
        }

        /// <summary>
        /// 发送配置串口
        /// </summary>
        /// <param name="isStopBits">Parity 是空校验 true </param>
        /// <param name="useBlock1K"> true 表示是1kxmodel  false还是 xmodel</param>
        public void SetSendSelectedPortConfig(string Ports, bool _useBlock1K = true, bool isStopBits = true)
        {
            serialPort1.ConfigSerialPort = new ConfigComType()
            {
                //PortName = comBoxPorts.Text,
                PortName = Ports,
                BaudRate = 115200,//xmodem波特率定死成115200,需要改3个地方setSelectedPortConfig、ConfigSerialPort、comBoxFSys_EditValueChanged
                                  //BaudRate = int.Parse(comBoxBaudRate.Text),
                                  //DataBits = int.Parse(comBoxDataBits.Text),
                DataBits = 8,
                StopBits = SerialPortHelperLib.StopBits.One,
                //Parity = isStopBits ? SerialPortHelperLib.Parity.None : (SerialPortHelperLib.Parity)Enum.Parse(typeof(SerialPortHelperLib.Parity), comBoxParity.EditValue.ToString()),
                Parity = isStopBits ? SerialPortHelperLib.Parity.None : SerialPortHelperLib.Parity.Even,

            };
            //初始化全局变量
            PackageTemp = 0;
            //useBlock1K = comBoxAgreement.EditValue.ToString() == "0" ? true : false;
            useCRC = -1;
            serialPort1.SerialReceviedTimeInterval = 5;
            serialPort1.SerialWriteTimeInterval = 0;
            useBlock1K = _useBlock1K;
        }

        /// <summary>
        /// 接收配置串口
        /// </summary>
        /// <param name="isStopBits">Parity 是空校验 true </param>
        /// <param name="useBlock1K"> true 表示是1kxmodel  false还是 xmodel</param>
        public void SetReceiveSelectedPortConfig( string Ports, bool _useBlock1K =true, bool isStopBits =true) {
            serialPort2.ConfigSerialPort = new ConfigComType()
            {
                //PortName = comBoxPorts.Text,
                PortName = Ports,
                BaudRate = 115200,//xmodem波特率定死成115200,需要改3个地方setSelectedPortConfig、ConfigSerialPort、comBoxFSys_EditValueChanged
                                  //BaudRate = int.Parse(comBoxBaudRate.Text),
                                  //DataBits = int.Parse(comBoxDataBits.Text),
                DataBits = 8,
                StopBits = SerialPortHelperLib.StopBits.One,
                //Parity = isStopBits ? SerialPortHelperLib.Parity.None : (SerialPortHelperLib.Parity)Enum.Parse(typeof(SerialPortHelperLib.Parity), comBoxParity.EditValue.ToString()),
                Parity = isStopBits ? SerialPortHelperLib.Parity.None : SerialPortHelperLib.Parity.Even,
            };
            //初始化全局变量
            PackageTemp = 0;
            //useBlock1K = comBoxAgreement.EditValue.ToString() == "0" ? true : false;
            useCRC = -1;
            serialPort2.SerialReceviedTimeInterval = 30;
            serialPort2.SerialWriteTimeInterval = 1;
            useBlock1K = _useBlock1K;
            //设置线程传送长度
            if (_useBlock1K)
            {
                serialPort2.SerialReceviedLengthMax = 1028;
            }
            else
            {
                serialPort2.SerialReceviedLengthMax = 132;
            }
        }
    }


   

}
